/* Include files. */

extern "C" { 
	#include "standard.h"
	#include "util.h"
	#include "debug.h"
} 

#include "object.h"
#include "ref.h"

/* Local function declarations. */

/* Macro API definitions. */

/* Global variable declarations. */

/* Type definitions. */

/* Local function definitions. */
map<string, object*> object::object_map_mgr;

object::object(string name, string alias, string subname, lua_State *L)
	:_name(name), _alias(alias), _subname(subname), _L(L)
{
}

object::~object()
{
	map<string, ref*>::iterator ite;
	for(ite = _ref_map_mgr.begin(); ite != _ref_map_mgr.end(); ite++) {
		ref *r = ite->second;
		delete r;
	}  
	_ref_map_mgr.clear();
}

object* object::findObject(string key)
{
	map<string, object*>::iterator ite = object_map_mgr.find(key);  
	if(ite != object_map_mgr.end()){
		return ite->second;
	}
	else{
		return NULL;
	}  
}

ref* object::findRef(string key)
{
	map<string, ref*>::iterator ite = _ref_map_mgr.find(key);  
	if(ite != _ref_map_mgr.end()){
		return ite->second;
	}
	else{
		return NULL;
	}  	
}

int object::add(ref *r)
{
	string key = r->_src + r->_attr;
	ref *r_ = findRef(key);
	if (r_ == NULL) {
		_ref_map_mgr[key] = r;
		return true;
	}
	else {
		return false;
	}	
}

int object::remove(string key)
{
	ref *r = findRef(key);
	if (r != NULL) {
		_ref_map_mgr.erase(key);
		delete r;
		return true;
	}
	else {
		return false;
	}
}

int luaregObject(lua_State *L) 
{
	object *obj;
	const char* name = lua_tostring(L, 1);
	const char* sub = lua_tostring(L, 2);
	int alias = lua_isstring(L, 3);
	if (alias) {
		obj = new object(name, lua_tostring(L, 3), sub, L);
		DEBUG("REG_OBJECT %s (%s)\n", obj->_name.c_str(), obj->_alias.c_str());
		object::object_map_mgr[obj->_alias] = obj;
	}
	else {
		obj = new object(name, "", sub, L);
		DEBUG("REG_OBJECT %s\n", obj->_name.c_str());
	}
	object::object_map_mgr[name] = obj;
	return 0;
}

int luaunRegObject(lua_State *L) 
{
	const char* name = lua_tostring(L, 1);
	object *obj = object::findObject(name);
	if (obj != NULL) {
		DEBUG("UNREG_OBJECT %s\n", name);
		object::object_map_mgr.erase(name);
		if (obj->_alias != "")
			object::object_map_mgr.erase(obj->_alias);
		delete obj;
	}
	else {
		ASSERT(0);
	}
	return 0;
}

int luagetObject(lua_State *L) 
{
	int pos = 0;
	const char* name = lua_tostring(L, 1);
	string str(name);
	while(true) {
		object *obj = object::findObject(str);
		if (obj != NULL) {
			lua_pushstring(L, str.c_str());
			return 1;
		}
		else {
			pos = str.find_last_of('.');
			if (pos != -1) {
				str = str.substr(0, pos);
			}
			else {
				lua_pushnil(L);
				return 1;
			}
		}
	}
}

int luagetObjectName(lua_State *L) 
{
	const char* name = lua_tostring(L, 1);
	object *obj = object::findObject(name);
	if (obj != NULL) {
		lua_pushstring(L, obj->_subname.c_str());
		lua_pushstring(L, obj->_name.c_str());
		return 2;
	}
	else {
		lua_pushnil(L);
		return 1;
	}
}

int luagetAllObject(lua_State *L) 
{
	lua_newtable(L);
	int i = 1;
	map<string, object*>::iterator ite;
	for(ite = object::object_map_mgr.begin(); ite != object::object_map_mgr.end(); ite++) {
		lua_pushnumber(L, i);
		string c(ite->first);
		c = c + ".";
		lua_pushstring(L, c.c_str());
		lua_settable(L, -3);
		i++;
	}  
	return 1;
}

